package model.components;

//import gui.Icons;
import model.SimulatorConstants;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Server Class. Subclass of Node.
 */
public class Server extends Node {
	
	/** Virtualization Software **/
	public enum VSoftware {VMWare, XEN, KVM, VirtualBox};
	
	public static final int MAX_VMS = 256;
	
	private int maxLogicalIfaces;
	
	private VSoftware vSoftware;
	private int diskSpace;
//	private List<VirtualMachine> virtualMachines;
	private List<NodeMapping> virtualMachines;

	public Server(int id) {
		super(id);
		name = "server"+id;
		virtualMachines = new CopyOnWriteArrayList<NodeMapping>();
		/*setIcon(Icons.SERVER);
		setSmallIcon(Icons.SERVER_SMALL);
		setPickedIcon(Icons.SERVER_PICKED);
		setYellowIcon(Icons.SERVER_YELLOW);
		setRedIcon(Icons.SERVER_RED);*/
		setMaxLogicalIfaces(SimulatorConstants.MAX_LOGICAl_IFACES_SERVER);
		/** Default VSoftware **/
		vSoftware = VSoftware.VMWare;
	}
	
	public VSoftware getvSoftware() {
		return vSoftware;
	}

	public void setvSoftware(VSoftware vSoftware) {
		this.vSoftware = vSoftware;
	}

	public int getDiskSpace() {
		return diskSpace;
	}

	public void setDiskSpace(int diskSpace) {
		this.diskSpace = diskSpace;
	}

	public List<NodeMapping> getVirtualMachines() {
		return virtualMachines;
	}

	public void setVirtualMachines(List<NodeMapping> virtualMachines) {
		this.virtualMachines = virtualMachines;
	}
	
//	public void addVirtualMachine(VirtualMachine vm) {
//		this.virtualMachines.add(vm);
//	}
	public void addVirtualMachine(NodeMapping vm) {
		this.virtualMachines.add(vm);
	}
	
	public void removeVirtualMachine(String reqId, int nodeId) {
		for (NodeMapping vm : virtualMachines)
			if (vm.getRequest().getId().equals(reqId)
					&& vm.getRequestNode().getId() == nodeId)
				virtualMachines.remove(vm);
	}
	
	public int getAvailableCpu() {
		int returnValue = this.getCpu();
		for (NodeMapping vm: virtualMachines)
			returnValue-=vm.getRequestNode().getCpu();
		return returnValue;
	}
	
	public int getAvailableMemory() {
		int returnValue = this.getMemory();
		for (NodeMapping vm: virtualMachines)
			returnValue-=vm.getRequestNode().getMemory();
		return returnValue;
	}
	
	public int getAvailableDiskSpace() {
		int returnValue = this.diskSpace;
		for (NodeMapping vm: virtualMachines)
			returnValue-=((VirtualMachine) vm.getRequestNode()).getDiskSpace();
		return returnValue;
	}
	
	public int getAvailableVlans(Collection<Link> links) {
		int returnValue = this.vlans;
		for (Link l : links)
			returnValue -= ((SubstrateLink) l).getVirtualLinks().size();
		return returnValue;
	}
	
	public int getMaxLogicalIfaces() {
		return maxLogicalIfaces;
	}

	public void setMaxLogicalIfaces(int maxLogicalIfaces) {
		this.maxLogicalIfaces = maxLogicalIfaces;
	}

//	public Object getCopy() {
//		Server s = new Server(this.getId());
//		s.name = this.name;
//		s.cpu = this.cpu;
//		s.memory = this.memory;
//		s.vlans = this.vlans;
//		s.so = this.so;
//		s.netStack = this.netStack;
//		s.location = this.location;
////		for (Interface i : this.interfaces)
////			s.interfaces.add((Interface) i.getCopy());
//		s.diskSpace = this.diskSpace;
//		s.vSoftware = this.vSoftware;
//		s.maxLogicalIfaces = this.maxLogicalIfaces;
//		for (VirtualMachine vm : this.virtualMachines)
//			s.virtualMachines.add((VirtualMachine) vm.getCopy());
//		return s;
//	}
	public Object getCopy() {
		Server s = new Server(this.getId());
		s.name = this.name;
		s.cpu = this.cpu;
		s.memory = this.memory;
		s.vlans = this.vlans;
		s.so = this.so;
		s.netStack = this.netStack;
		s.location = this.location;
//		for (Interface i : this.interfaces)
//			s.interfaces.add((Interface) i.getCopy());
		s.diskSpace = this.diskSpace;
		s.vSoftware = this.vSoftware;
		s.maxLogicalIfaces = this.maxLogicalIfaces;
		for (NodeMapping nm : this.virtualMachines)
			s.virtualMachines.add(nm.getCopy());
		return s;
	}
	
}
